package com.xbongbong.parent.explain;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.TemplateFieldEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkDetailPojo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.EditFieldTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.pojo.nodes.FormTriggerNode;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 梁鲁江
 * @version v1.0
 * @date 2019/3/28 16:20
 * @since v1.0
 */
@Component
public class HandleExplainHelp {
    private static final Logger LOG = LoggerFactory.getLogger(HandleExplainHelp.class);

    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowModel workflowModel;
    /**
     * 该方法来自 FormDataListFormExplainHandleName ，为了方便引用迁移致此
     * @param handlerExplainDTO
     * @return
     * @throws XbbException
     */
    public HandlerExplainVO handleExplain(HandlerExplainDTO handlerExplainDTO) throws XbbException {
        HandlerExplainVO handlerExplainVO = new HandlerExplainVO();
        try {
            List<FieldAttrEntity> explainList = handlerExplainDTO.getExplainList();
            PaasFormEntityExt paasFormEntityExt = handlerExplainDTO.getPaasFormEntityExt();
            Integer saasMark = paasFormEntityExt.getSaasMark();
            Set<String> editAttrSet = new HashSet<>();
            Set<Integer> editAttrFieldTypeSet = EditFieldTypeEnum.getEditFieldTypeSet();
            if (SaasMarkEnum.SAAS.getCode().equals(saasMark)) {
                // 获取saas可编辑字段
                Integer businessType = paasFormEntityExt.getBusinessType();
                businessType = XbbRefTypeEnum.transferBusinessType4Distributor(businessType, paasFormEntityExt.getDistributorMark());
                XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
                editAttrSet = ExplainUtil.getSaasEditAttr(xbbRefTypeEnum);
                businessType = XbbRefTypeEnum.transferBusinessType2Index(businessType);

            }
            // 需过滤的不能编辑的审批字段
            List<String> approvalEditAttrLis = getApprovalEditAttrs(paasFormEntityExt);
            // 获取套餐
            List<String> featureList = packageHelp.getFeatureList(handlerExplainDTO.getCorpid());
            List<FieldAttrEntity> list = new ArrayList<>();
            for (FieldAttrEntity entity: explainList) {
                //列表页过滤字段
//                if (entity.getEditHide() != null && entity.getEditHide() == 1){
//                    continue;
//                }
                //列表页过滤富文本
                if (Objects.equals(entity.getFieldType(), FieldTypeEnum.RICH_TEXT.getType())){
                    continue;
                }
                //列表页过滤富文本编辑器(服务项目)
                if (Objects.equals(entity.getFieldType(), FieldTypeEnum.RICH_TEXT_EDITOR.getType())){
                    continue;
                }
                if (!ShowTypeEnum.listShow(entity.getShowType())){
                    continue;
                }
                // 字段回收站处理
                if (Objects.equals(entity.getIsOpen(), 2)) {
                    entity.setVisible(0);
                }
                // 套餐逻辑，标准版本隐藏复杂字段
                packageHelp.explainHide(featureList, entity);

                //选择产品字段，过滤非列表字段
                List<FieldAttrEntity> subJsonArray = new ArrayList<>();
                SubFormPoJo subForm = entity.getSubForm();
                if (Objects.equals(entity.getFieldType(),FieldTypeEnum.SELECT_PRODUCT.getType())){
                    if (subForm != null && subForm.getItems() != null) {
                        Iterator<? extends FieldAttrEntity> iterator = subForm.getItems().iterator();
                        while (iterator.hasNext()){
                            FieldAttrEntity subFieldAttrEntity = iterator.next();
                            if (!ShowTypeEnum.listShow(subFieldAttrEntity.getShowType())){
                                continue;
                            }
                            // 字段回收站处理
                            if (Objects.equals(subFieldAttrEntity.getIsOpen(), 2)) {
                                subFieldAttrEntity.setVisible(0);
                            }
                            if (Objects.equals(SelectProductEnum.UNIT.getAttr(),subFieldAttrEntity.getAttr())){
                                proFormHelp.setSelectProductItem(subFieldAttrEntity,handlerExplainDTO.getCorpid());
                            }
                            subJsonArray.add(subFieldAttrEntity);
                        }
                        subForm.setItems(subJsonArray);
                    }
                    proFormHelp.setProductAccuracy(entity,handlerExplainDTO.getCorpid(),handlerExplainDTO.getUserId());
                }

                // 允许可见，则处理以下规则
                // TODO 高级可见规则需要增加
                Integer fieldType = entity.getFieldType();
                // 可编辑字段列表不为空，并且包含该字段
                boolean saasEditAttr = true;
                if (SaasMarkEnum.SAAS.getCode().equals(saasMark)) {
                    saasEditAttr = !editAttrSet.isEmpty() && editAttrSet.contains(entity.getAttr());
                }
                // 根据业务判断列表的字段是否可以编辑
                boolean allowEditFlag = editAttrFieldTypeSet.contains(fieldType);
                if (allowEditFlag) {
                    // 允许编辑的，需要判断是否需审批字段
                    allowEditFlag = !approvalEditAttrLis.contains(entity.getAttr());
                }
                // 只有非扩展字段才走这个逻辑
                if (entity.getIsRedundant().equals(0)) {
                    // 非扩展字段，并且未开启时，字段不能显示在列表上
                    if (Objects.equals(entity.getIsOpen(), 0) && handlerExplainDTO.getIsFilter()) {
                        continue;
                    }
                    if (entity.getEditable().equals(1) && saasEditAttr && allowEditFlag){
                        entity.setEditable(1);
                    } else {
                        entity.setEditable(0);
                    }
                } else {
                    //阶段推进器字段是扩展字段 所以也要判断是否开启
                    if (Objects.equals(entity.getIsOpen(), 0) && handlerExplainDTO.getIsFilter()) {
                        continue;
                    }
                    // 扩展字段
                    if (approvalEditAttrLis.contains(entity.getAttr())) {
                        entity.setEditable(0);
                    }
                }
                if(entity.getVisible().equals(1) && !fieldType.equals(FieldTypeEnum.LINK_QUERY.getType())
                        && !fieldType.equals(FieldTypeEnum.MEMO.getType()) && !fieldType.equals(FieldTypeEnum.SEPARATOR.getType())){
                    if (ExplainUtil.isSubForm(entity.getFieldType())) {
                        if (subForm != null && subForm.getItems() != null) {
                            List<? extends FieldAttrEntity> subExplainList = subForm.getItems();
                            List<FieldAttrEntity> resultList = new ArrayList<>();
                            for(FieldAttrEntity fieldAttrEntity: subExplainList){
                                if(Objects.equals(1, fieldAttrEntity.getVisible()) && !Objects.equals(FieldTypeEnum.LINK_QUERY.getType(), fieldAttrEntity.getFieldType())){
                                    // 子表单字段不可以编辑
                                    fieldAttrEntity.setEditable(0);
                                    resultList.add(fieldAttrEntity);
                                }
                                if (Objects.isNull(fieldAttrEntity.getVisible()) || Objects.isNull(fieldAttrEntity.getFieldType())) {
                                    LOG.info("visible is null ：" + fieldAttrEntity.getAttr() + "；name：" + fieldAttrEntity.getAttrName());
                                }
                            }
                            // 如果子表单内没有可见字段，则无需将子表单字段返回
                            if (resultList.isEmpty()) {
                                continue;
                            }
                            subForm.setItems(resultList);
                        }
                    }
                    entity.setItems(proFormHelp.setItem(entity, paasFormEntityExt));
                    if (Objects.equals(handlerExplainDTO.getBusinessType(), XbbRefTypeEnum.PRODUCT.getCode()) && (Objects.equals(handlerExplainDTO.getSubBusinessType(), XbbRefTypeEnum.STOCK_SEARCH.getCode())
                            || Objects.equals(handlerExplainDTO.getSubBusinessType(), XbbRefTypeEnum.WARNING_SEARCH.getCode()) || Objects.equals(handlerExplainDTO.getSubBusinessType(), XbbRefTypeEnum.GUARANTEE_SEARCH.getCode()))) {
                        entity.setEditable(0);
                    }
                    if (Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())
                            || Objects.equals(fieldType, FieldTypeEnum.LINK_BUSINESS_MULTI.getType())) {
                        // 系统关联字段拼装属性
                        LinkDetailPojo linkDetail = new LinkDetailPojo();
                        linkDetail.setBusinessType(entity.getLinkedType());
                        linkDetail.setSubBuisenssType(entity.getLinkedType());
                        linkDetail.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        entity.setDistributorMark(paasFormEntityExt.getDistributorMark());
                        entity.setLinkDetail(linkDetail);
                    }
                    if(Objects.equals(fieldType, FieldTypeEnum.TEMPLATE_FIELD.getType())) {
                        SubFormPoJo newSubForm = new SubFormPoJo();
                        List<FieldAttrEntity> resultList = new ArrayList<>();
                        FieldAttrEntity templateNmae = new FieldAttrEntity();
                        templateNmae.setEditable(0);
                        templateNmae.setAttrName(TemplateFieldEnum.TEMPLATE_NAME.getName());
                        FieldAttrEntity file = new FieldAttrEntity();
                        file.setEditable(0);
                        file.setAttrName(TemplateFieldEnum.FILE.getName());
                        resultList.add(templateNmae);
                        resultList.add(file);
                        newSubForm.setItems(resultList);
                        entity.setSubForm(newSubForm);
                    }
                    list.add(entity);
                }
            }

            handlerExplainVO.setHeadList(list);
        } catch (Exception e){
            LOG.error("处理字段中的部门、角色、用户等名称报错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return handlerExplainVO;
    }

    /**
     * 获取审批通过后允许编辑情况下，需要审批的字段
     * @param paasFormEntityExt 表单
     * @return List
     */
    private List<String> getApprovalEditAttrs(PaasFormEntityExt paasFormEntityExt) {
        List<String> approvalEditAttrLis = new ArrayList<>();
        if (!Objects.equals(1,paasFormEntityExt.getIsProcessForm())) {
            // 不是流程表单
            return approvalEditAttrLis;
        }
        if (commonHelp.isOpenWorkFlow(paasFormEntityExt.getCorpid())) {
            // 获取含有审批节点，并且是当前使用（即enable=1，is_approve=1）的工作流
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, paasFormEntityExt.getCorpid());
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("appId",paasFormEntityExt.getAppId());
            params.put("menuId",paasFormEntityExt.getMenuId());
            params.put("formId",paasFormEntityExt.getId());
            params.put("saasMark", paasFormEntityExt.getSaasMark());
            params.put("businessType", paasFormEntityExt.getBusinessType());
            params.put("currentVersion", 1);
            params.put("enable",1);
            params.put("isApprove", 1);
            params.put("triggerEventTypeIn", Arrays.asList(TriggerEventTypeEnum.ADD_OR_UPDATE.getType(), TriggerEventTypeEnum.ONLY_UPDATE.getType()));
            params.put(StringConstant.COLUMNS, "id");
            List<WorkflowEntity> list = workflowModel.findEntitys(params);
            if (CollectionUtils.isEmpty(list)) {
                return approvalEditAttrLis;
            }
            Set<Long> workflowIdList = new HashSet<>();
            list.forEach(item->workflowIdList.add(item.getId()));
            // 获取起始节点，拿到起始节点，获取需审批字段
            params.clear();
            params.put(StringConstant.CORPID, paasFormEntityExt.getCorpid());
            params.put(StringConstant.DEL, 0);
            params.put("appId",paasFormEntityExt.getAppId());
            params.put("menuId",paasFormEntityExt.getMenuId());
            params.put("formId",paasFormEntityExt.getId());
            params.put("workflowIdIn", workflowIdList);
            params.put("type", WorkflowNodeTypeEnum.START_NODE.getType());
            List<WorkflowNodeEntity> workflowNodeList = workflowNodeModel.findEntitys(params);
            Set<String> approvalEditAttr = new HashSet<>();
            workflowNodeList.forEach(item->{
                FormTriggerNode formTriggerNode = JSON.parseObject(item.getConfigData(), FormTriggerNode.class);
                if (Objects.nonNull(formTriggerNode)) {
                    List<String> approveList = formTriggerNode.getNeedApproveFields();
                    approveList = approveList == null ? new ArrayList<>() : approveList;
                    approvalEditAttr.addAll(approveList);
                }
            });
            approvalEditAttrLis.addAll(approvalEditAttr);
        } else {
            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("del", 0);
            map.put("appId",paasFormEntityExt.getAppId());
            map.put("menuId",paasFormEntityExt.getMenuId());
            map.put("formId",paasFormEntityExt.getId());
            map.put("corpid",paasFormEntityExt.getCorpid());
            map.put("enable",1);
            map.put(ParameterConstant.COLUMNS, " need_approve_fields as need_approve_field_list, allow_edit_after_finished ");
            List<PaasProcessTemplateEntityExt> processTemplateList = paasProcessTemplateModel.list(map);
            if (processTemplateList.isEmpty()) {
                return approvalEditAttrLis;
            }
            PaasProcessTemplateEntityExt paasProcessTemplateEntityExt = processTemplateList.get(0);
            List<String> needApproveFieldList = paasProcessTemplateEntityExt.getNeedApproveFieldList();
            Integer allowEditAfterFinished = paasProcessTemplateEntityExt.getAllowEditAfterFinished();
//        if (1 == allowEditAfterFinished && Objects.nonNull(needApproveFieldList) && !needApproveFieldList.isEmpty()) {
            if (Objects.nonNull(needApproveFieldList) && !needApproveFieldList.isEmpty()) {
                //审批通过后允许编辑，并且有需审批字段，需审批需要禁止快速/批量编辑
                approvalEditAttrLis.addAll(needApproveFieldList);
            }
        }
        return approvalEditAttrLis;
    }

}
